#include "oled.h"
#include "i2c.h"
#include "string.h"

extern u8g2_t u8g2;

/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
static uint8_t buffer[128];
static uint8_t buf_idx;
uint8_t *data;


/*
 * @brief  u8g2 硬件 I2C 通信函数
 * @param  u8x8: u8g2 结构体指针
 * @param  msg: 消息类型
 * @param  arg_int: 参数
 * @param  arg_ptr: 参数指针
 * @retval 0: 失败 1: 成功
 */
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  switch (msg) {
    case U8X8_MSG_BYTE_INIT:
      // I2C初始化可选，如果在外部已初始化则无需重复
      break;

    case U8X8_MSG_BYTE_START_TRANSFER:
      buf_idx = 0;
      break;

    case U8X8_MSG_BYTE_SEND:
      data = (uint8_t *)arg_ptr;
      memcpy(buffer + buf_idx, data, arg_int);
      buf_idx += arg_int;
      break;

    case U8X8_MSG_BYTE_END_TRANSFER:
      HAL_I2C_Master_Transmit_DMA(&hi2c1, OLED_ADDRESS, buffer, buf_idx);
      while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY) {}
      break;

    case U8X8_MSG_BYTE_SET_DC:
      // DC 信号通常用于 SPI，与 I2C 无关，可忽略
      break;

    default:
      return 0;
  }
  return 1;
}

/**
 * @brief  u8g2 延时函数
 * @param  u8x8: u8g2 结构体指针
 * @param  msg: 消息类型
 * @param  arg_int: 参数
 * @param  arg_ptr: 参数指针
 * @retval None
 */
uint8_t stm32_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  switch (msg) {
    case U8X8_MSG_DELAY_100NANO:
      __NOP();
      break;

    case U8X8_MSG_DELAY_10MICRO:
      for (uint16_t n = 0; n < 320; n++) {
        __NOP();
      }
      break;

    case U8X8_MSG_DELAY_MILLI:
      HAL_Delay(arg_int);
      break;

    case U8X8_MSG_DELAY_I2C:
      for (uint16_t n = 0; n < 160; n++) {
        __NOP();
      }
      break;

    case U8X8_MSG_GPIO_I2C_CLOCK:
    case U8X8_MSG_GPIO_I2C_DATA:
      // I2C 硬件模式下通常无需处理这些 GPIO 信号
      break;

    case U8X8_MSG_GPIO_MENU_SELECT:
    case U8X8_MSG_GPIO_MENU_NEXT:
    case U8X8_MSG_GPIO_MENU_PREV:
    case U8X8_MSG_GPIO_MENU_HOME:
      u8x8_SetGPIOResult(u8x8, 0);
      break;

    default:
      u8x8_SetGPIOResult(u8x8, 1);
      break;
  }
  return 1;
}

/** OLED 初始化函数 */
void oled_init(void)
{
  u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, stm32_gpio_and_delay);
  u8g2_InitDisplay(&u8g2);
  u8g2_SetPowerSave(&u8g2, 0);  // 关闭省电模式，开启显示
}


